package flash3.net
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	
	import flash3.framework.Map;
	import flash3.framework.Singleton;
	
	import net.MessageDef;
	import net.MessageGroup;
	
	import view.plugin.MessageOut;
	
	public class NetFacade extends Singleton
	{
		private var _socket:BaseConnect;
		private var _handle:INetConnect;
		private var _trace:Boolean;
		private var _messages:MessageGroup;
		private var _msg1:Map;
		private var _msg2:Map;
		private var _dispatch:EventDispatcher = null;
		
		public function NetFacade():void
		{
		}
		
		public function init(outLog:Boolean = true):void
		{
			_trace = outLog;
			_messages = new MessageGroup();
			_messages.registerGroup();
			_dispatch = new EventDispatcher();
			_msg1 = new Map();
			_msg2 = new Map();
		}
		
		public function addEventListener(type:String, listener:Function):void
		{
			_dispatch.addEventListener(type, listener);	
		}
		
		public function removeEventListener(type:String, listener:Function):void
		{
			_dispatch.removeEventListener(type, listener);	
		}
		
		public function connect(host:String, port:uint, handle:INetConnect=null):void
		{
			_handle = handle;
			if(_socket)
			{
				_socket.removeEventListener(Event.CONNECT, onConnectSucceed);
				_socket.removeEventListener(IOErrorEvent.IO_ERROR, onIOError);
				_socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
				_socket.removeEventListener(Event.CLOSE, onConnectClose);
				_socket.removeEventListener(PacketEvent.SOCKET_SEND, onSendData);
				_socket.removeEventListener(ProgressEvent.SOCKET_DATA, onReciveData);
				_socket = null;
			}
			_socket = new BaseConnect();
			_socket.addEventListener(Event.CONNECT, onConnectSucceed);
			_socket.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			_socket.addEventListener(Event.CLOSE, onConnectClose);
			_socket.addEventListener(PacketEvent.SOCKET_SEND, onSendData);
			_socket.addEventListener(ProgressEvent.SOCKET_DATA, onReciveData);
			_socket.connect(host, port);
		}
		
		public function send(mainid:uint, subid:uint, data:*=null, parm:Object = null):void
		{
			var msgDef:MessageDef = _messages.getMessageDef(mainid, subid);
			if(!msgDef)
				throw new Error("错误的消息id");
			var packet:MsgPacket = new MsgPacket();
			packet._id = mainid;
			packet._subid = subid;
			packet._type = MsgPacket.MSG_SEND;
			packet._parm = data;
			msgDef._analy(packet);
			//acall(mainid, subid, parm);
			_socket.send(packet);
		}
		
		public function close():void
		{
			if(_socket)
				_socket.close();
		}
		
		public function acall(mainid:uint, subid:uint, parm:Object):void
		{
			if(!parm) return;
			
			var map:Map;
			var temp:Boolean;
			if(_msg1.containsKey(mainid))
			{
				map = _msg1.getValue(mainid) as Map;
			}
			else
			{
				_msg1.put(mainid, map = new Map());
			}
			
			map.put(subid, parm);
		}
		public function rcall(mainid:uint, subid:uint):void
		{
			var map:Map;
			if(!_msg1.containsKey(mainid) || !((map= _msg1.getValue(mainid) as Map).containsKey(subid)))
				return;
			map.remove(subid);
		}
		private function callHandle(packet:MsgPacket):void
		{
			var map:Map;
			
			if(!_msg1.containsKey(packet._id) || !((map= _msg1.getValue(packet._id) as Map).containsKey(packet._subid)))
				return;
			
			var obj:Object = map.getValue(packet._subid);
			
			obj.call(packet);
			
			if(!obj.forever || obj.forever == false)
				map.remove(packet._subid);
		}
		
		private function onConnectSucceed(evt:Event):void
		{
			if(_handle)
				_handle.onConnectSucceed(evt);
			_dispatch.dispatchEvent(evt);
		}
		
		private function onIOError(evt:IOErrorEvent):void
		{
			if(_handle)
				_handle.onIOError(evt);
			_dispatch.dispatchEvent(evt);
		}
		
		private function onSecurityError(evt:SecurityErrorEvent):void
		{
			if(_handle)
				_handle.onSecurityError(evt);
			_dispatch.dispatchEvent(evt);
		}
		
		private function onConnectClose(evt:Event):void
		{
			if(_handle)
				_handle.onConnectClose(evt);
			_dispatch.dispatchEvent(evt);
		}
		
		public function set handle(hd:INetConnect):void
		{
			_handle = hd;
		}
		
		private function onSendData(evt:PacketEvent):void
		{
			var packet:MsgPacket = evt._packet;
			//callHandle(packet);
			outLog("请求：" + _messages.getMessageDef(packet._id, packet._subid)._desc);
		}
		
		private function onReciveData(evt:PacketEvent):void
		{
			var packet:MsgPacket = evt._packet;
			var msgDef:MessageDef = _messages.getMessageDef(packet._id, packet._subid);
			if(!msgDef)
				throw new Error("错误的消息id:mainid:"+packet._id+"/subid:"+packet._subid);
			packet._type = MsgPacket.MSG_RECIVE;
			msgDef._analy(packet);
			outLog("通知：" + msgDef._desc);
			callHandle(packet);
		}
		
		private function outLog(log:String):void
		{
			if(_trace)
			{
				trace(log);
				MessageOut.i.outMessage(log);
			}
		}
		
		public function get socket():BaseConnect
		{
			return _socket;
		}
		
		static public function get i():NetFacade
		{
			return Singleton.getInstanceOrCreate(NetFacade) as NetFacade;
		}
		
		public function get messageGroup():MessageGroup
		{
			return _messages;
		}
	}
}